/*
* sound.c
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
#include "avcodec.h"
#include <sys/time.h>


#define LENGTH 3    /* 存储秒数 */
#define RATE 8000   /* 采样频率 */
#define SIZE 8      /* 量化位数 */
#define CHANNELS 1  /* 声道数目 */

/* 用于保存数字音频数据的内存缓冲区 */

#define AUDIO_BLOCK_SIZE 8164
typedef struct {
    int fd;
    int sample_rate;
    int channels;
    int frame_size; /* in bytes ! */
    unsigned char buffer_in[AUDIO_BLOCK_SIZE];
    unsigned char buffer_out[AUDIO_BLOCK_SIZE];
    int buffer_ptr;
} AudioData;
    unsigned char buf_out[AUDIO_BLOCK_SIZE];

#define EIO -1
static int audio_open(AudioData *s, const char *audio_device)
{
    int audio_fd;
    int tmp, err;

    /* open linux audio device */
    if (!audio_device)
        audio_device = "/dev/dsp";
        
    audio_fd = open(audio_device, O_RDONLY);

    if (audio_fd < 0) {
        perror(audio_device);
        return -EIO;
    }

    s->frame_size = AUDIO_BLOCK_SIZE;

    /* select format : favour native format */
    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
    if (tmp & AFMT_S16_LE) {
        tmp = AFMT_S16_LE;
    } else if (tmp & AFMT_S16_BE) {
        tmp = AFMT_S16_BE;
    } else {
        tmp = 0;
    }
    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
    if (err < 0) {
        perror("SNDCTL_DSP_SETFMT");
        goto fail;
    }

    tmp = (s->channels == 2);
printf ("tem=%d\n",tmp);
    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
    if (err < 0) {
        perror("SNDCTL_DSP_STEREO");
        goto fail;
    }
    if (tmp)
        s->channels = 2;
    
    tmp = s->sample_rate;
    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
    if (err < 0) {
        perror("SNDCTL_DSP_SPEED");
        goto fail;
    }
    s->sample_rate = tmp; /* store real sample rate */
    s->fd = audio_fd;

    return 0;
 fail:
    close(audio_fd);
    return -EIO;
}
/*
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
*/
//extern AVCodec adpcm_ima_qt_encoder;
void register_codec(){
#define PCM_CODEC(id, name) \
    register_avcodec(& name ## _encoder); \
    register_avcodec(& name ## _decoder); \
	/*
	PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le);
	PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be);
	PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le);
	PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be);
	PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8);
	PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8);
	PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
	PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);*/

    /* adpcm codecs */
	PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt);
	PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav);
	PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
	PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
	PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
	PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
#undef PCM_CODEC
	return;
}
int main()
{
	int status;   /* 系统调用的返回值 */
	FILE *fp;
	int dsp_out;
	AudioData sound;
	AVCodecContext myAVcode;
	AVCodecContext myAVdecode;
	int frame_bytes,ret,data_size;
   struct  timeval tv;
   int rt;
   struct timezone tz;	
   int setting =0;

	dsp_out = open("/dev/dsp1", O_WRONLY);

	setting=(0x4<<16)+(0x0a);
	ioctl(dsp_out, SNDCTL_DSP_SETFRAGMENT, &setting);
		
	sound.channels=1;
	sound.sample_rate=8000;

	audio_open(&sound,"/dev/dsp");


	myAVcode.sample_rate=sound.sample_rate;
	myAVcode.channels=sound.channels;
	myAVdecode.sample_rate=sound.sample_rate;
	myAVdecode.channels=sound.channels;
	register_codec();
	avcodec_open(&myAVcode, avcodec_find_encoder(CODEC_ID_ADPCM_IMA_WAV));
	avcodec_open(&myAVdecode, avcodec_find_decoder(CODEC_ID_ADPCM_IMA_WAV));

	setting=(0x8<<16)+(0x0a);
	ioctl(sound.fd, SNDCTL_DSP_SETFRAGMENT, &setting);

	/* 循环，直到按下Control-C */
       frame_bytes = myAVcode.frame_size * 2 * myAVcode.channels;
	printf ("code name=%d  framesize=%d frame_bytes=%d\n",myAVcode.codec_id,myAVcode.frame_size,frame_bytes);

/*	fp=fopen("sound.dat","rb");
	while (!feof(fp)) {
		status = read(sound.fd, &sound.buffer_in, frame_bytes); // 录音
		fread(buf_out,512,1,fp);
		ret=512;
		avcodec_decode_audio(&myAVdecode,(short *)sound.buffer_out,&data_size,(char *)buf_out,ret);
		printf ("end %d datasize=%d\n",512,data_size);
		write(dsp_out,&sound.buffer_out, data_size);
	}*/

//	fp=fopen("sound.dat","rb");
	while (1) {
			gettimeofday(&tv,&tz);
			printf ("begin %ld ",tv.tv_usec/1000);
		status = read(sound.fd, &sound.buffer_in, frame_bytes); // 录音
		if (status !=frame_bytes)
			printf ("read wrong number of bytes=%d \n",status);
		else{
       		ret = avcodec_encode_audio(& myAVcode, buf_out, frame_bytes, (short *) &sound.buffer_in);
//			fwrite(buf_out,512,1,fp);fflush(fp);
//			fread(buf_out,256,1,fp);
			avcodec_decode_audio(&myAVdecode,(short *)sound.buffer_out,&data_size,(char *)buf_out,512);
			gettimeofday(&tv,&tz);
			printf ("end1 %ld ",tv.tv_usec/1000);
			rt=write(dsp_out,&sound.buffer_out, data_size);
			printf ("rt= %ld\n",rt);
		}
	}
}

